#include "cInit_hy188d.h"
#include "cardReaderDev.h"
#include "des.h"
#include <QString>
#include "sm4.h"
#include "sm3.h"
#include "hyTool.h"
#include "script.h"
#include "hex_bin.h"

namespace SDHuaYi_Script
{
    using namespace SDHuaYi_Utils;

    COSInit188D::COSInit188D()
    {
    }

    qint32 COSInit188D::BinAnalize(QString sBinFileContent)
    {
        return 0;
    }

    qint32 COSInit188D::IniAnalize(QString sIniFileContent) {
        return 0;
    }

    qint32 COSInit188D::CalculateCmdNM() {
        return  0;
    }

    qint32 COSInit188D::Authertication(EnumAuthMod iMOD, qint32 iflag, QString sCardType) {
        return  0;
    }

    // 返回下载模式
    bool COSInit188D::BackToDl()
    {
        // 卡片上电
        if (!iReader.CardReset())
        {
            return false;
        }
        // 处于非下载模式
        if (iReader.Card.strATS != "3B848001009D000199")
        {
            QString sAuth = "";

            cosAuth(sAuth);

            cosBackToDownload();
        }
        if (!iReader.CardReset())
        {
            return false;
        }
        // 处于非下载模式
        if (iReader.Card.strATS != "3B848001009D000199")
        {
            return false;
        }
        return true;
    }

    // 下载模式认证
    bool COSInit188D::DlAuth()
    {
        QString sKSEED = "7962D9ECE03D1ACD4C76089DCE131543";
        QString sRNDPCD = "781723860C06C226";
        QString sKPCD = "0B795240CB7049B01C19B33E32804F0B";

        // 卡片上电复位
        if (false == iReader.CardReset())
        {
            return false;
        }

        // 生成加密密钥和MAC密钥
        if ((false == iReader.SendAPDU("0017000000")) || (iReader.SS() != "9000"))
        {
            return false;
        }

        // 取随机数
        if ((false == iReader.SendAPDU("0084000008")) || (iReader.SS() != "9000"))
        {
            return false;
        }

        QString sRandom = iReader.Response();

        // 调整奇偶校验
        QString sKenc = HYALG_SM3Hash(sKSEED + "00000001");
        HYString::adjustParityBitsToOdd(sKenc);

        QString sKmac = HYALG_SM3Hash(sKSEED + "00000002");
        HYString::adjustParityBitsToOdd(sKmac);

        QString sDataEnc;

        sDataEnc = HYALG_SM4Crypt(ALG_MODE_CBC, ALG_ENC, sKenc, "00000000000000000000000000000000", sRNDPCD + sRandom + sKPCD);

        QString sDataMac;
        sDataMac = HYALG_SM4Crypt(ALG_MODE_MAC, ALG_ENC, sKmac, "00000000000000000000000000000000", sDataEnc);

        if ((false == iReader.SendAPDU("0019000030" + sDataEnc + sDataMac)) || (iReader.SS() != "9000"))
        {
            return false;
        }

        /*增加指令0078018c04f102e384*/
        if ((false == iReader.SendAPDU("0078018C04F102E384")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        return true;
    }

    // 安全写入
    bool COSInit188D::cosDownLoad(QString &message)
    {
        // TODO:支持3个固件下载

        /* 下载客户自定义算法库 */
        if (!updataUserAlgLibFilePath.isEmpty())
        {
            Hex_Bin userAlgLib = Hex_Bin(updataUserAlgLibFilePath, iReader);
            if (!userAlgLib.Get_Order())
            {
                throw std::runtime_error("解析用户自定义算法库文件失败");
            }
            userAlgLib.Send_Cos();
        }

        /* 下载HY算法库 */
        if (!updataAlgLibFilePath.isEmpty())
        {
            Hex_Bin algLib = Hex_Bin(updataAlgLibFilePath, iReader);
            if (!algLib.Get_Order())
            {
//                throw std::runtime_error("解析HY算法库文件失败");
            }
            algLib.Send_Cos();
        }

        /* 下载用户COS */
        if (!updataFirmwareFilePath.isEmpty())
        {
            Hex_Bin cosfirmware = Hex_Bin(updataFirmwareFilePath, iReader);
            if (!cosfirmware.Get_Order())
            {
                throw std::runtime_error("解析用户cos文件失败");
            }
            cosfirmware.Send_Cos();
        }

        return true;
    }

    // 用户模式初始化
    bool COSInit188D::cosConfig(QString &sUID2, QString &sAuthCode)
    {

        // 用户模式认证
        if (false == cosAuth(sAuthCode))
        {
            return false;
        }
        // 初始化配置区
        if ((false == iReader.SendAPDU("00DB00FF00")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        // 配置typeA或typeB UID
        if ((false == iReader.SendAPDU("00DB00000DA70B00800000200800" + sUID2)) || (iReader.SS() != "9000"))
        {
            return false;
        }
        // 配置ATS ATR
        if ((false == iReader.SendAPDU("00DB000017A115B1047880D002B20D4D5400180040000019" + sUID2)) || (iReader.SS() != "9000"))
        {
            return false;
        }
        if ((false == iReader.SendAPDU("00DB00001BA219B1080D11000A20040001B20D4D5400180040000019" + sUID2)) || (iReader.SS() != "9000"))
        {
            return false;
        }
        // 配置COS信息
        if ((false == iReader.SendAPDU("00DB000012A810188D202402190001464A4D4B00000000")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        // 卡片初始化完成
        if ((false == iReader.SendAPDU("00FF00001639000000FF33FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")) || (iReader.SS() != "9000"))
        {
            return false;
        }

        // 卡片上电复位
        if (false == iReader.CardReset())
        {
            return false;
        }
        // 获取UID
        if ((false == iReader.SendAPDU("00DDFD0004")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        QString newUID = iReader.Response();

        if ((newUID != sUID2) || (iReader.Card.strATS != ("3B8D80014D5400180040000019" + sUID2 + "54")))
        {
            return false;
        }
        return true;
    }

    // 复位自检
    bool COSInit188D::ResetCheck(QString &sUID2)
    {
        // 卡片上电复位
        if (false == iReader.CardReset())
        {
            return false;
        }

        if ((false == iReader.SendAPDU("FFCC00000193")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        QString newATS = iReader.Response();
        if (newATS != ("127880D0024D5400180040000019" + sUID2))
        {
            return false;
        }
        return true;
    }

    QString Bit_Reversal(QString str)
    {
        int len = str.size();
        bool ok;
        unsigned char buf[64] = "";
        for (int i = 0; i < len / 2; ++i)
        {
            buf[i] = str.mid(i * 2, 2).toInt(&ok, 16);
        }

        for (int j = 0; j < len / 2; ++j)
        {
            for (int k = 0; k < 8; ++k)
            {
                if (buf[j] & (1 << k)) // 如果该位为1
                {
                    buf[j] &= ~(1 << k);
                    qDebug() << k;
                }
                else
                {
                    buf[j] |= (1 << k);
                }
            }
        }
        QString outstr = "";
        for (int h = 0; h < len / 2; ++h)
        {
            outstr.append(QString::number(buf[h], 16).rightJustified(2, '0'));
        }

        return outstr.toUpper();
    }

    // 用户模式认证流程
    bool COSInit188D::cosAuth(QString &sAuthCode)
    {
        QString sKey = "4879434F5356362E305F313830345631";

        // 卡片复位
        if (false == iReader.CardReset())
        {
            return false;
        }
        // 取UID
        if ((false == iReader.SendAPDU("00DDFD0004")) || (iReader.SS() != "9000"))
        {
            return false;
        }

        QString sUID = iReader.Response().mid(0, 8) + "00000000";
        QString sUID_F = Bit_Reversal(sUID);

        if (iAlgType == HYALG_3DES)
        {
            QString ssKey1, ssKey2, ssKey;

            ssKey1 = HYALG_DESCrypt(ALG_MODE_CBC, ALG_ENC, sKey, "0000000000000000", sUID);
            ssKey2 = HYALG_DESCrypt(ALG_MODE_CBC, ALG_ENC, sKey, "0000000000000000", sUID_F);

            ssKey = ssKey1.mid(0, 16) + ssKey2.mid(0, 16);

            // 取16字节随机数
            if (false == iReader.SendAPDU("00DDFE0010") || (iReader.SS() != "9000"))
            {
                return false;
            }

            QString sData, sData1, sData2;
            sData1 = HYALG_DESCrypt(ALG_MODE_CBC, ALG_ENC, ssKey, "0000000000000000", iReader.Response().mid(0, 16));
            sData2 = HYALG_DESCrypt(ALG_MODE_CBC, ALG_ENC, ssKey, "0000000000000000", iReader.Response().mid(16, 16));

            sData = sData1.mid(0, 16) + sData2.mid(0, 16);

            if ((false == iReader.SendAPDU("00DD000010" + sData)) || (iReader.SS() != "9000"))
            {
                return false;
            }
        }
        else if (iAlgType == HYALG_SM4)
        {
            char *sUID_INV = sUID.toUtf8().data();

            for (int i = 0; i < 4; i++)
            {
                // UID取反
                sUID_INV[i] = (char)(sUID_INV[i] ^ (0xFF));
            }

            QString strINV_UID = QString(sUID_INV);

            QString ssKey1, ssKey2, ssKey;
            ssKey1 = HYALG_SM4Crypt(ALG_MODE_CBC, ALG_ENC, sKey, "00000000000000000000000000000000", sUID + "0000000000000000");
            ssKey2 = HYALG_SM4Crypt(ALG_MODE_CBC, ALG_ENC, sKey, "00000000000000000000000000000000", strINV_UID + "FFFFFFFFFFFFFFFF");

            ssKey = ssKey1.mid(0, 16) + ssKey2.mid(0, 16);

            // 取16字节随机数
            if (false == iReader.SendAPDU("00DDFE0010") || (iReader.SS() != "9000"))
            {
                return false;
            }

            QString sData, sData1, sData2;
            sData1 = HYALG_SM4Crypt(ALG_MODE_CBC, ALG_ENC, ssKey, "00000000000000000000000000000000", iReader.Response().mid(0, 16));
            sData2 = HYALG_SM4Crypt(ALG_MODE_CBC, ALG_ENC, ssKey, "iReader.Response().mid(0, 16)", sData2);

            sData = sData1.mid(0, 16) + sData2.mid(0, 16);

            if ((false == iReader.SendAPDU("00DD000010" + sData)) || (iReader.SS() != "9000"))
            {
                return false;
            }
        }
        else
        {
            return false;
        }

        // 备份认证码
        if (false == iReader.SendAPDU("00DDFB0000"))
        {
            return false;
        }
        if (iReader.SS() != "9000")
        {
            sAuthCode = iReader.Response();
        }
        else
        {
            sAuthCode = "000000000000000000";
        }

        return true;
    }

    // Flash复位
    bool COSInit188D::FlashReset()
    {
        if ((false == iReader.SendAPDU("0040000000")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        // 卡片复位
        if (!iReader.CardReset())
        {
            return false;
        }
        //  判断是否进入用户
        if (iReader.Card.strATS == "3B848001009D000199")

        {
            return false;
        }
        return true;
    }

    // 返回下载模式指令/*00DB 00FE 00*/
    bool COSInit188D::cosBackToDownload()
    {
        if ((false == iReader.SendAPDU("00DB00FE00")) || (iReader.SS() != "9000"))
        {
            return false;
        }
        return true;
    }

}
